﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace APNS.NET
{

    // Reads feedback from the apns service
    public class FeedbackService : IDisposable
    {
     
        private readonly Stream _feedbackStream;

        private const string DefaultSandboxHost = "feedback.sandbox.push.apple.com";
        private const string DefaultProductionHost = "feedback.push.apple.com";
        private const int DefaultPort = 2196;

        public static FeedbackService OpenFeedbackChannel(X509Certificate apnCertificate, bool useSandbox)
        {
            if (useSandbox)
                return OpenFeedbackChannel(DefaultSandboxHost, DefaultPort, apnCertificate);
            else
                return OpenFeedbackChannel(DefaultProductionHost, DefaultPort, apnCertificate);
        }

        public static FeedbackService OpenFeedbackChannel(string hostname, int port, X509Certificate apnCertificate)
        {
            return new FeedbackService(new ApnsStream(hostname, port, apnCertificate));
        }

        internal FeedbackService(Stream feedbackStream)
        {
            this._feedbackStream = feedbackStream;
        }

        ~FeedbackService()
        {
            Dispose(false);
        }

        public IEnumerable<Feedback> CheckForFeedback()
        {
            byte[] buffer = new byte[38];
            while(true)
            {
                int bytesRead = _feedbackStream.Read(buffer, 0, buffer.Length);
                if(bytesRead==0)
                    break;

                yield return Feedback.FromBytes(buffer);
            }
        }

        public void Close()
        {
            _feedbackStream.Close();
        }

        public void Dispose(bool disposing)
        {
            Close();
            if(disposing)
            {
                _feedbackStream.Dispose();
            }
        }

        public void Dispose()
        {
            Dispose(true);
        }
    }
}
